
/*
0.96 气象站 SPI 高德API 7.0版 配套源码
更新日志：
高德API_1_能够获取并解析高德天气API
高德API_2_移除部分无用代码，具备简单的天气显示功能
高德API_3_界面3替换BF加入电量显示功能
高德API_4_高德与和风图标代码兼容
高德API_5_湿度位置判断显示
高德API_5.1_关闭电量显示_修正天气图片逻辑
高德API_5.2_中文显示两位风力_修改index为高德
高德API_5.3_加入及修正注释部分
高德API_5.4_将风力换为风向
高德API_5.5_加入电量显示
高德API_5.5.1_当电量小于0时改为其它显示
高德API_5.5.2_修正天气图标逻辑
高德API_5.5.3_修正"雷阵雨"时对应天气图标不显示
高德API_6.0_移除重复头文件引用_将NTP服务器的固定IP获取改为根据域名解析获取，试图解决NTP服务器偶尔获取不到数据导致时间不能正常显示的问题_加入软重启:用于解决因硬重启或程序崩溃重启后无法连接至网络的问题(IP unset)_加入WiFi连接状态判断配合软重启
高德API_6.1_更快的未联网重启(对wifi_link_tool-master配网库进行修改，将软重启移至wifi_link_tool.h中)_从Arduino IDE迁移到Visual Studio Code
高德API_7.0_将ESP-12F开发板板载标识替换为ESP8266的GPIO，更具通用性，从此版本开始将支持不同大小FLASH的文件上传

基于 ”0.96 气象站 第3版 配套源码“
By 磁阻教主 二次作者：南湘小隐  原作者：发明控
*/

#include <string.h>
#define FS_CONFIG
//兼容1.1.x版本库
#include <wifi_link_tool.h>
#include <ArduinoJson.h>
#include <Arduino.h>
#include <U8g2lib.h>
#include <EEPROM.h>
#include "zlt.h"

#include <Time.h>
#include <TimeLib.h>
#include <WiFiUdp.h>
#include <WiFiClientSecure.h>

#include <WiFiClientSecureBearSSL.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

String  keys  = "aa762598f95bad9ff77b0f6bc7c674cf";  // 高德天气接口地址：https://lbs.amap.com/dev/key/app 需要自己申请key
String  dq  = "510100"; //  填入城市编号  下载城市编码表获取编号：https://lbs.amap.com/api/webservice/download
String  UID = "45100348";    //  B站UID,用以显示粉丝数

String page = "3"; //设定显示界面1.B站粉丝界面/2.天气界面/ 3.天气第二界面/4.高考倒计时
#define sck 5 /* 屏幕 */
#define sda 4

const int CONFIG_HTTPPORT   = 80;
const int CONFIG_HTTPSPORT  = 443;

std::unique_ptr<BearSSL::WiFiClientSecure>client( new BearSSL::WiFiClientSecure );


// U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/4, /* dc=*/5, /* reset=*/12);
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2( U8G2_R0, /* clock=*/ sck, /* data=*/ sda, /* reset=*/ U8X8_PIN_NONE );
int             col   = 999;
String          diqu    = "";   
int             tq    = 0;      //天气代码
String          pm2   = "";     //pm2.5
String          aqi   = "";     //空气质量参数
String          hum   = "";     //空气湿度
String          wdir   = "";     //风向
String          bfs   = "NO UID";//bilbili 粉丝数
String          wendu   = "";    //温度
String          tim   = "00:00"; 
String          dat   = "2023/01/01";
int             previousday    =  0;    //用于判断是否过了一天6
//int             previousminutes  =  0;    //用于判断分钟改变后刷新屏幕
int             lastday    =     1 ;   //倒计时天数

unsigned long     previousMillis  = 0;
const long        interval  = 30000;        /* 30秒更新屏幕 */
unsigned long     previousMillis2 = 0;
const long        interval2 = 180000;      /* 半小时更新天气  */
unsigned long     previousMillis3 = 0;
const long        interval3 = 70000;       /* 动画更新时间 ，避免和屏幕刷新时间冲突*/ 

int flag1 = 0;   //网页参数是否修改标记
int flag2 = 0;
int flag3 = 0;
int flag4 = 0;
int flag6 = 0;
int flag5 = 0;   //所有网页函数是否都运行完成

int pcboot = 0; //pc请求识别
//IPAddress timeServer( 120, 25, 115, 20 );                         /* 阿里云ntp服务器 如果失效可以使用 120.25.115.19   120.25.115.20 */
static const char ntpServerName[] = "time1.aliyun.com";           //NTP服务器域名
#define STD_TIMEZONE_OFFSET +8                                    /* 设置中国 */
const int timeZone = 8;                                           /* 修改北京时区 */
WiFiUDP   Udp;

unsigned int  localPort = 8266;                                    /* 修改udp 有些路由器端口冲突时修改 */
int   servoLift = 1500;

int sensorValue = 0; // 从引脚读到的值
double outputValue = 0; // 映射电压值
double maxValue = 4.2; // 电量百分比电压上限(100%对应的电压值)
double minValue = 3.5; // 电量百分比电压下限(0%对应的电压值)


// 获取网页信息服务开启 3/3 对应1的处理函数
void zdws(){  // 高德天气keys
  String a= webServer.arg("zdws");
  if(a != "" && a != get_String(EEPROM.read(3000),3001))  //如果网页获取的参数不是空值 且 与flash中的值不同
    {
    keys = a ;
    set_String(3000,3001,keys);
    flag1 = 1 ; // 标志着网页参数1改变
    }
    flag5 = flag5+1; //本函数运行之后 ，标志位加1
    Serial.println("高德天气keys"); 
    Serial.println(keys);  
}
void wsdw(){  //城市id
  String b= webServer.arg("wsdw");
  if(b != "" && b != get_String(EEPROM.read(3100),3101) )
    {
    dq = b ;
    set_String(3100,3101,dq);
    flag2 = 1 ; // 标志着网页参数2改变
    }
    flag5 = flag5+1; //本函数运行之后 ，标志位加1
    Serial.println("城市id"); 
    Serial.println(dq);  
}
void yggd(){     //b站uid
  String c= webServer.arg("yggd");
  if(c != "" && c != get_String(EEPROM.read(3200),3201) )
    {
    UID = c ;
    set_String(3200,3201,UID);
    flag3 = 1 ; // 标志着网页参数3改变 
    }
    flag5 = flag5+1; //本函数运行之后 ，标志位加1
    Serial.println("b站uid"); 
    Serial.println(UID);  

}
void txhm(){       //界面选择：1.B站粉丝界面；2天气界面； 3天气第二界面
  String d= webServer.arg("txhm");
  if(d != "" && d != get_String(EEPROM.read(3300),3301))
    {
    page = d ;
    set_String(3300,3301,page);
    flag4 = 1 ; // 标志着网页参数4改变
    }
    flag5 = flag5+1; //本函数运行之后 ，标志位加1
    Serial.println("界面选择"); 
    Serial.println(page);  
    

}
void zgwd(){   // 倒计时数据处理
  String e= webServer.arg("zgwd");
  EEPROM.get(3400,lastday); 
  if(e != ""  && e.toInt() != lastday )
  {
    lastday = e.toInt();
    EEPROM.put(3400,lastday); 
    EEPROM.commit();
    flag6 = 1;
  }
  Serial.println("倒计时"); 
  Serial.println(lastday);  
  flag5 = flag5+1; //本函数运行之后 ，标志位加1
  Serial.println("网页函数运行数量"); 
  Serial.println(flag5);  
  if(flag5 > 4) //5个函数都运行了,执行重启的动作
    {
      if(flag1 == 1 || flag2 == 1 || flag3 == 1 || flag4 == 1 || flag6 == 1)  //任一一个参数发生改变
        {
         setok(); //设定完成后屏幕提示完成
 //        flag1 = 0;  //重启后，这些参数都恢复默认值
 //        flag2 = 0;
 //        flag3 = 0;
 //        flag4 = 0;
 //        flag5 = 0;    
         ESP.restart();  //判断逻辑是，如果都执行了且有参数改变后才重启
        }
    }
}

//写入字符串函数
//a写入字符串长度位置，b是起始位，str为要保存的字符串
void set_String(int a,int b,String str){
  EEPROM.write(a, str.length());//EEPROM第a位，写入str字符串的长度
  //把str所有数据逐个保存在EEPROM
  for (int i = 0; i < str.length(); i++){
    EEPROM.write(b + i, str[i]);
  }
  EEPROM.commit();
}

//读字符串函数
//a位是字符串长度，b是起始位
String get_String(int a, int b){ 
  String data = "";
  //从EEPROM中逐个取出每一位的值，并链接
  for (int i = 0; i < a; i++){
    data += char(EEPROM.read(b + i));
  }
  return data;
}



//高考倒计时函数
void djs()
{   
   int currentday =day(); 
   if(currentday != previousday )
   {
       previousday = currentday;
       if(lastday != 0)
       {
       lastday = lastday - 1 ; 
       EEPROM.put(3400,lastday);       //将此值写入flash
       EEPROM.commit();
       }
       //Serial.println("previousday"); 
       //Serial.println(previousday);
       //Serial.println("lastday"); 
       //Serial.println(lastday);   
   } 
}
/*
//时间刷新
void timerefrash(){
  int currentminutes = minute();
  if(currentminutes != previousminutes )
   {
    previousminutes = currentminutes;
    shuaxin();  //刷新屏幕
    //Serial.println("previousminutes"); 
    //Serial.println(previousminutes);   
   }
}
*/

//参数设定确认界面
void setok(){
  u8g2.clearBuffer();
  u8g2.drawXBMP( 0, 5, 20, 20, ok1 ); //参数设置完成
  u8g2.drawXBMP( 20, 5, 20, 20, ok2 );
  u8g2.drawXBMP( 40, 5, 20, 20, ok3 );
  u8g2.drawXBMP( 60, 5, 20, 20, ok4 );
  u8g2.drawXBMP( 80, 5, 20, 20, ok5 );
  u8g2.drawXBMP( 100, 5, 20, 20, ok6 );
  u8g2.drawXBMP( 30, 30, 20, 20, ok7 );//重启中
  u8g2.drawXBMP( 50, 30, 20, 20, ok8 );
  u8g2.drawXBMP( 70, 30, 20, 20, ok9 );
  u8g2.sendBuffer();
  delay(2000);
}
/* //////////////////////////////////////////////////天气数据 */
void xx()
{
  String line;
  std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);  
  client->setInsecure();  
  HTTPClient https;  
  if (https.begin(*client, "https://restapi.amap.com/v3/weather/weatherInfo?city="+dq+"&key="+keys))
  {  
      // 获取可用的 heap 内存大小，并输出到串口监视器
      Serial.println("可用的 heap 内存大小为：" + String(ESP.getFreeHeap()));
      
      int httpCode = https.GET();  //此处很容易引发Exception (29)错误崩溃重启

      // 获取可用的 heap 内存大小，并输出到串口监视器
      Serial.println("可用的 heap 内存大小为：" + String(ESP.getFreeHeap()));
      
      if (httpCode > 0) 
      {  
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) 
        {  
          line = https.getString();  
        }  
      } 
      https.end();  
    } else {  
      Serial.printf("[HTTPS]请求链接失败\n");  
    } 
  Serial.println("接口返回"+line);
  
  DynamicJsonBuffer jsonBuffer(1024);
  JsonObject& res_json = jsonBuffer.parseObject(line);
  // 访问 JSON 对象中的数组
  JsonArray& lives = res_json["lives"];
  JsonObject& live = lives[0];   // 取第一个元素
  
  String sheng=live["province"];
  String shi=live["city"];
  
  String r1=sheng+shi;//地区
  String r2=live["weather"];//天气
  String r3=live["temperature"];//温度
  String r4=live["humidity"]; //湿度
  String r5=live["windpower"]; //风力
  String r6=live["winddirection"]; //风向
  
  jsonBuffer.clear();
  diqu  = r1; /* 地区 */
  if ( r2 != 0 )
  {                          
    tianqibiao(r2);
  }
  if ( r3 != "" )
  {                          
     wendu = r3;                //体感温度 
     hum = r4;             //湿度
     aqi = r5;       //空气质量(改为风力)
     wdir = r6;  //风向
  }         
}

//天气刷新函数
void sjfx()
{
  delay( 1000 );
  
  // 获取可用的 heap 内存大小，并输出到串口监视器
  Serial.println("可用的 heap 内存大小为：" + String(ESP.getFreeHeap()));
  
  xx();
  delay( 1000 );

  // 获取可用的 heap 内存大小，并输出到串口监视器
  Serial.println("可用的 heap 内存大小为：" + String(ESP.getFreeHeap()));
  
  col = tq;
  //Serial.println("天气刷新中..."); 
  Serial.println( "当前地区： " + diqu );
  //Serial.println( "天气代码： " );
  //Serial.println( tq );
  //Serial.println( "体感温度： " + wendu );
  //Serial.println( "PM2.5： " + pm2 );
}

//电量显示函数
void dianliang(){
  //读取模拟输入数值
  sensorValue = analogRead(A0);
  // 使用map函数把输入的数值进行映射
  outputValue = map(sensorValue, 0, 1024, 0, 440);//可以修改数值映射440   4.4V
//  u8g2.clearBuffer();
  if ( outputValue >= 300 )
  {
    u8g2.setFont( u8g2_font_squeezed_b6_tr );
    u8g2.setFontDirection(0);
    u8g2.setCursor(85,63);
    u8g2.print(int((((outputValue/100)-minValue)/(maxValue-minValue))*100));
  }
//  u8g2.print("%");
//  u8g2.sendBuffer(); 
}

//b站粉丝采集函数
void blbluid() 
{
   WiFiClient client;
   HTTPClient http;
   if (http.begin(client, "http://api.bilibili.com/x/relation/stat?vmid="+UID)) 
   {
       int httpCode = http.GET();
       String payload = http.getString();
       http.end();
       DynamicJsonBuffer jsonBuffer;
       JsonObject& res_json = jsonBuffer.parseObject(payload);
       String follower = res_json["data"]["follower"];
       if(follower!="") 
       {
         bfs=follower;
       }
       jsonBuffer.clear();
   }
}

void tubiao( ){
  
  if (col==100||col==150){  //晴      
 u8g2.drawXBMP(0,0,40,40,col_100);    
   
  }else if (col==102||col==101){        
 u8g2.drawXBMP(0,0,40,40,col_102);//云 
         
  }else  if (col==103||col==153){        
 u8g2.drawXBMP(0,0,40,40,col_103);//晴间多云 
           
  }else if (col==104||col==154){        
 u8g2.drawXBMP(0,0,40,40,col_104);//阴   
         
  }else if (col>=300&&col<=301){        
 u8g2.drawXBMP(0,0,40,40,col_301);//阵雨 
           
  }else if (col>=302&&col<=303){        
 u8g2.drawXBMP(0,0,40,40,col_302);//雷阵雨   
     
  }else if (col==304){        
 u8g2.drawXBMP(0,0,40,40,col_304);//冰雹  
         
  }else if (col==399||col==314||col==305||col==306||col==307||col==315||col==350||col==351){        
 u8g2.drawXBMP(0,0,40,40,col_307);//雨   
        
  }else if ((col>=308&&col<=313)||(col>=316&&col<=318)){        
 u8g2.drawXBMP(0,0,40,40,col_310);//暴雨    
       
  }else if ((col>=402&&col<=406)||col==409||col==410||col==400||col==401||col==408||col==499||col==456){        
 u8g2.drawXBMP(0,0,40,40,col_401);//雪  
         
  }else if (col==407||col==457){        
 u8g2.drawXBMP(0,0,40,40,col_407);//阵雪  
          
  }else if (col>=500&&col<=502){        
 u8g2.drawXBMP(0,0,40,40,col_500);//雾霾  
          
  }else if (col>=503&&col<=508){        
 u8g2.drawXBMP(0,0,40,40,col_503);//沙尘暴 
           
  }else if (col>=509&&col<=515){        
 u8g2.drawXBMP(0,0,40,40,col_509);//不适宜生存  
        
  }else{      
 u8g2.drawXBMP(0,0,40,40,col_999);//未知
  }
}

//屏幕刷新函数
void shuaxin(){

if(pcboot==0){
  
 /* setSyncProvider(getNtpTime); */
  String zov = "";
  String zod = "";
  if ( hour() < 10 )
  {
    zov = "0";
  }
  if ( minute() < 10 )
  {
    tim = zov + String( hour() ) + ":0" + String( minute() );
  }else{ tim = zov + String( hour() ) + ":" + String( minute() ); }
  if( month() < 10 )
  {
    zod = "0";
  }
  if ( day() < 10 )
  {
    dat = String( year() ) + "/" + zod + String( month() ) + "/0" + String( day() );
  }else{
    dat = String( year() ) + "/" + zod + String( month() ) + "/" + String( day() );
  }

  Serial.print( tim );    /* 输出当前网络分钟 */
  Serial.print( dat );    /* 输出当前日期 */
  u8g2.clearBuffer();
  tubiao(); //天气图标
   
  if(page == "1")    //1.B站粉丝界面
     {      
                blbluid();          //刷新b站粉丝
                u8g2.setFont( u8g2_font_ncenB18_tf );
                u8g2.setFontDirection( 0 );
                u8g2.setCursor( 65, 53 );
                u8g2.print( wendu );    //温度
                u8g2.setFont( u8g2_font_wqy12_t_chinese2 );
                u8g2.setFontDirection( 0 );
                u8g2.setCursor( 63, 64 );
                u8g2.print( dat );      //日期 
                u8g2.drawXBMP(103,37,16,16,col_ssd1);
                u8g2.setFont( u8g2_font_ncenR12_tf );
                u8g2.setFontDirection( 0 );
                u8g2.setCursor(0,50);
                u8g2.print("bilibili");
  
               // u8g2.drawXBMP( 0, 39, 12, 12, id1 ); //稚晖君
               // u8g2.drawXBMP( 12, 39, 12, 12, id2 );
               // u8g2.drawXBMP( 24, 39, 12, 12, id3 );
      
                u8g2.setFont(u8g2_font_bauhaus2015_tn); 
                u8g2.setCursor(0,64);
                u8g2.print(bfs);  // 刷新粉丝 
                u8g2.setFont( u8g2_font_fub25_tf );
                u8g2.setFontDirection( 0 );
                u8g2.setCursor( 40, 32 );
                u8g2.print( tim );
                u8g2.sendBuffer();
     }else if(page == "2" )  // 2.默认天气界面  pm2.5
     {
                u8g2.setFont(u8g2_font_ncenB18_tf);  
                u8g2.setFontDirection(0); 
                u8g2.setCursor(65,53);
                u8g2.print(wendu);   //温度
                u8g2.setFont(u8g2_font_wqy12_t_chinese2);  
                u8g2.setFontDirection(0);
                u8g2.setCursor(63,64);
                u8g2.print(dat);  //日期
                u8g2.drawXBMP(103,37,16,16,col_ssd1);
                u8g2.setFont(u8g2_font_ncenR12_tf);  
                u8g2.setFontDirection(0);  
                u8g2.setCursor(0,48);
                u8g2.print("pm2.5");
                u8g2.setCursor(10,62);
                u8g2.print(pm2); //pm2.5 浓度
                u8g2.setFont(u8g2_font_fub25_tf);  
                u8g2.setFontDirection(0);
                u8g2.setCursor(40,32);
                u8g2.print(tim);
                u8g2.sendBuffer(); 
      
     }else if (page == "3") //3.天气界面  温湿度  aqi
     {
              if(wendu.length() < 3){
                u8g2.drawXBMP(30,38,16,16,col_ssd1);
                u8g2.setFont(u8g2_font_VCR_OSD_tf);  
                u8g2.setFontDirection(0); 
                u8g2.setCursor(5,53);
                u8g2.print(wendu);          //体感温度
               }else{
                u8g2.setFont(u8g2_font_VCR_OSD_tf);  
                u8g2.setFontDirection(0); 
                u8g2.setCursor(5,53);
                u8g2.print(wendu);          //体感温度
               }
              u8g2.setFont(u8g2_font_8x13_t_symbols);  
              u8g2.setFontDirection(0);
              u8g2.setCursor(3,64);
              u8g2.print(dat);            //日期
//              u8g2.setFont(u8g2_font_8x13_t_symbols);  
//              u8g2.setFontDirection(0);  
//              u8g2.setCursor(102,64);
//              u8g2.print("BF");    //空气质量符号

//              u8g2.setFont(u8g2_font_wqy12_t_gb2312);   
//              u8g2.setFontDirection(0);  
//              u8g2.setCursor(100,63);
//              u8g2.print("风力");    //风力
              
              if( wdir.length() < 4 ){
                u8g2.setFont(u8g2_font_wqy12_t_gb2312);   
                u8g2.setFontDirection(0);  
                u8g2.setCursor(106,63);
                u8g2.print(wdir);    //风向
              }else{
                u8g2.setFont(u8g2_font_wqy12_t_gb2312);   
                u8g2.setFontDirection(0);  
                u8g2.setCursor(100,63);
                u8g2.print(wdir);    //风向
              }
              

              
              if( hum.length() < 3 ){
                u8g2.setFont(u8g2_font_VCR_OSD_tf);  
                u8g2.setFontDirection(0); 
                u8g2.setCursor(52,53);
                u8g2.print(hum);          //实际湿度
                u8g2.setFont(u8g2_font_luBS12_tr);  
                u8g2.setFontDirection(0);  
                u8g2.setCursor(77,52);
                u8g2.print("%");
              }else{
                u8g2.setFont(u8g2_font_VCR_OSD_tf);  
                u8g2.setFontDirection(0); 
                u8g2.setCursor(46,53);
                u8g2.print(hum);          //实际湿度
                u8g2.setFont(u8g2_font_luBS12_tr);  
                u8g2.setFontDirection(0);  
                u8g2.setCursor(84,52);
                u8g2.print("%");
              }
                  
              if( aqi.length() < 2 ){//原始aqi字节数<3
                u8g2.setFont(u8g2_font_VCR_OSD_tf);  
                u8g2.setFontDirection(0); 
                u8g2.setCursor(106,53);//原始aqi位置100,53
                u8g2.print(aqi);           //空气质量数值(改为风力)
              }else{
                u8g2.setFont(u8g2_font_wqy14_t_gb2312);  
                u8g2.setFontDirection(0); 
                u8g2.setCursor(102,50);//原始aqi位置92,53
                u8g2.print(aqi);           //空气质量数值(改为风力)
              }
              u8g2.setFont( u8g2_font_fub25_tf );  //u8g2_font_fub25_tf
              u8g2.setFontDirection(0);
              u8g2.setCursor(40,30);
              u8g2.print(tim);            //时间
                dianliang();            //电量
                u8g2.sendBuffer(); 

     }else if (page == "4")  //4.倒计时界面
     {
                u8g2.setFont( u8g2_font_ncenB18_tf );
                u8g2.setFontDirection( 0 );
                u8g2.setCursor( 65, 53 );
                u8g2.print( wendu );    //温度
                u8g2.setFont( u8g2_font_wqy12_t_chinese2 );  //u8g2_font_6x10_tf
                u8g2.setFontDirection( 0 );
                u8g2.setCursor( 63, 64 );
                u8g2.print( dat );      //日期 
                u8g2.drawXBMP( 103, 37, 16, 16, col_ssd1 );
  
                u8g2.drawXBMP( 0, 39, 12, 12, gk1 ); //距升本
                u8g2.drawXBMP( 17, 39, 12, 12, gk6 );
                u8g2.drawXBMP( 34, 39, 12, 12, gk7 );
                u8g2.drawXBMP( 36, 52, 12, 12, gk4 ); //天
      
                u8g2.setFont(u8g2_font_bauhaus2015_tn  ); 
                u8g2.setCursor(6,64);
                u8g2.print(lastday);  // 刷新倒计时天数 
                u8g2.setFont( u8g2_font_fub25_tf );
                u8g2.setFontDirection( 0 );
                u8g2.setCursor( 40, 32 );
                u8g2.print( tim );
                u8g2.sendBuffer();
      }
  }else
  { 
    pcboot=0;
  }
}


/*天气表函数：用于高德API的天气数据与和风天气的图标绑定

高德天气现象表：https://lbs.amap.com/api/webservice/guide/tools/weather-code/#t1
和风图标代码：https://dev.qweather.com/docs/resource/icons/
unicode编码转换：http://www.gongjula.com/unicode
*/
void tianqibiao(String weather)
{
  Serial.println(weather);
  if (weather  == "\u6674")  // 晴
  {
    tq  = 100;
    Serial.println("执行晴的代码");
  }
  if (weather  == "\u96e8" || weather  == "\u5c0f\u96e8" || weather  == "\u4e2d\u96e8" || weather  == "\u5927\u96e8" || weather  == "\u5c0f\u96e8\u002d\u4e2d\u96e8" || weather  == "\u4e2d\u96e8\u002d\u5927\u96e8") // 雨  小雨  中雨  大雨  小雨-中雨 中雨-大雨 
  {
    tq  = 305;
    Serial.println("执行雨  小雨  中雨  大雨  小雨-中雨 中雨-大雨 的代码");
  }
  if (weather  == "\u5c11\u4e91") // 少云
  {
    tq  = 102;
    Serial.println("执行少云的代码");
  }
  if (weather  == "\u6674\u95f4\u591a\u4e91" || weather  == "\u591a\u4e91") // 晴间多云 多云
  {
    tq  = 103;
    Serial.println("执行晴间多云 多云的代码");
  }
  if (weather  == "\u9634") //阴
  {
    tq  = 104;
    Serial.println("执行阴的代码");
  }
  if (weather  == "\u9635\u96e8") //阵雨
  {
    tq  = 300;
    Serial.println("执行阵雨的代码");
  }
  if (weather  == "\u66b4\u96e8"|| weather  == "\u5927\u66b4\u96e8" || weather  == "\u7279\u5927\u66b4\u96e8" || weather  == "\u5f3a\u9635\u96e8" || weather  == "\u5f3a\u96f7\u9635\u96e8" || weather  == "\u96f7\u9635\u96e8" || weather  == "\u6781\u7aef\u964d\u96e8"  ) //暴雨  大暴雨 特大暴雨 强阵雨 强雷阵雨 雷阵雨 极端降雨
  {
    tq  = 302;
    Serial.println("执行暴雨  大暴雨 特大暴雨 强阵雨 强雷阵雨 极端降雨的代码");
  }
  //if (weather  == "\u98ce") //风
  //{
  //  tq  = 104;
  //  Serial.println("执行风的代码");
  //}

  //if (weather  == "\u51b0\u96f9") //冰雹
  //{
  //  tq  = 104;
  //  Serial.println("执行冰雹的代码");
  //}

  if (weather  == "\u5927\u96e8\u002d\u66b4\u96e8" || weather  == "\u66b4\u96e8\u002d\u5927\u66b4\u96e8") //大雨-暴雨  暴雨-大暴雨
  {
    tq  = 316;
    Serial.println("执行大雨-暴雨  暴雨-大暴雨的代码");
  }
  if (weather  == "\u96ea"|| weather  == "\u5c0f\u96ea" || weather  == "\u4e2d\u96ea" ) //雪  小雪 中雪  
  {
    tq  = 409;
    Serial.println("执行雪  小雪 中雪  的代码");
  }
  if (weather  == "\u9635\u96ea"|| weather  == "\u5927\u96ea" || weather  == "\u66b4\u96ea" ) //阵雪 大雪 暴雪 
  {
    tq  = 457;
    Serial.println("执行 阵雪 大雪 暴雪 的代码");
  }
  if (weather  == "\u973e"|| weather  == "\u4e2d\u5ea6\u973e" || weather  == "\u91cd\u5ea6\u973e" || weather  == "\u4e25\u91cd\u973e" ) //霾  中度霾  重度霾 严重霾

  {
    tq  = 500;
    Serial.println("霾  中度霾  重度霾 严重霾的代码");
  }
  if (weather  == "\u6d6e\u5c18"|| weather  == "\u626c\u6c99" || weather  == "\u6c99\u5c18\u66b4" || weather  == "\u5f3a\u6c99\u5c18\u66b4"  ) // 浮尘 扬沙 沙尘暴 强沙尘暴 
  {
    tq  = 503;
    Serial.println("浮尘 扬沙 沙尘暴 强沙尘暴 ");
  }
  //if (weather  == "\u4e0d\u9002\u5b9c\u751f\u5b58") //不适宜生存
  //{
  //  tq  = 104;
  //  Serial.println("执行不适宜生存的代码");
  //}

  Serial.println("天气表执行结束");
}



void pc() 
{
  pcboot=1;
  String clk=webServer.arg("clk");
  String cpu=webServer.arg("cpu");
  String ram=webServer.arg("ram");
  String cput=webServer.arg("cput");
  webServer.arg("cpuv");
  u8g2.clearBuffer();
  u8g2.drawXBMP(0,0,128,64,pctp);
  u8g2.setFont(u8g2_font_crox5hb_tf);  
  u8g2.setFontDirection(0); 
  u8g2.setCursor(33,25);
  u8g2.print(cpu);  //cpu
  u8g2.setCursor(33,57);
  u8g2.print(cput); //cput
  u8g2.setCursor(95,57);
  u8g2.print(ram); //ram
  u8g2.setFont(u8g2_font_ncenR10_tf);  
  u8g2.setFontDirection(0); 
  u8g2.setCursor(96,16);
  u8g2.print(clk); //mhz
  u8g2.setCursor(94,30);
  u8g2.print("MHz"); 
  u8g2.sendBuffer(); 
  webServer.send(200, "text/plain", "ojbk");
}
  



//第一个动画效果 bilibili

void donghua2()
{
   int i = 0;
   u8g2.clearBuffer();
   for(i=0;i<=4;i++)
    {
      u8g2.drawXBMP(0,0,128,64,bili_Logo_1);
      u8g2.sendBuffer();
      delay(66);
    
      u8g2.drawXBMP(0,0,128,64,bili_Logo_2);
      u8g2.sendBuffer();
      delay(66);
    
      u8g2.drawXBMP(0,0,128,64,bili_Logo_3);
      u8g2.sendBuffer();
      delay(66);
      
      u8g2.drawXBMP(0,0,128,64,bili_Logo_2);
      u8g2.sendBuffer();
      delay(66);
    }
}


/* ////////////////////////////////////////////////////////////////解包设置////////////////////////////////////////////////////////////////////////////////////////////////////////////// */
void printDigits( int digits )
{
  Serial.print( ":" );
  if ( digits < 10 )
    Serial.print( '0' );
  Serial.print( digits );
}


void digitalClockDisplay()
{
  /*  */
  Serial.print( hour() );
  printDigits( minute() );
  Serial.println();
}



/*
@功能:获取网络时间部分代码
@说明:太复杂，不看~
*/
const int NTP_PACKET_SIZE = 48; // NTP时间在消息的前48字节
byte packetBuffer[NTP_PACKET_SIZE]; //保存传入和传出数据包的缓冲区
void sendNTPpacket( IPAddress &address )
{
  memset( packetBuffer, 0, NTP_PACKET_SIZE );

  packetBuffer[0] = 0b11100011;
  packetBuffer[1] = 0;
  packetBuffer[3] = 0xEC;

  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  Udp.beginPacket( address, 123 );
  Udp.write( packetBuffer, NTP_PACKET_SIZE );
  Udp.endPacket();
}
time_t getNtpTime(void){
  IPAddress ntpServerIP; // NTP服务器IP地址

  while (Udp.parsePacket() > 0) ; // 丢弃任何先前收到的数据包
  Serial.println("发送NTP请求");
  // 从池中获取一个随机服务器
  WiFi.hostByName(ntpServerName, ntpServerIP);
  Serial.print(ntpServerName);
  Serial.print(": ");
  Serial.println(ntpServerIP);
  sendNTPpacket(ntpServerIP);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // 将数据包读入缓冲区
      unsigned long secsSince1900;
      // 将从位置40开始的四个字节转换为长整数
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("无NTP响应 :-(");//没连接到NTP服务器
  return 0; // return 0 if unable to get the time
}



void setup()
{
  // 设置引脚为模拟输入模式
  pinMode(A0, INPUT);//电量读取引脚
  WiFiServer    HTTPserver( CONFIG_HTTPPORT );
  WiFiServerSecure  HTTPSserver( CONFIG_HTTPSPORT );
  Serial.begin( 115200 );// 开启串口
  /* ///////////////////////////////////////////////////////基础设置////////////////////////////////////////////////////////*/
  rstb = 0;   /* 重置io */
  stateled = 2;  /* 指示灯io */
  Hostname = "oled气象站";  /* 设备名称 允许中文名称 不建议太长 */
  wxscan = true;  /* 是否被小程序发现设备 开启意味该设备具有后台 true开启 false关闭 */
  
  u8g2.begin();
  u8g2.enableUTF8Print();
  u8g2.setFont( u8g2_font_unifont_t_chinese2 );
  u8g2.setFontDirection( 0 );
  u8g2.clearBuffer();
  u8g2.setCursor( 0, 15 );
  u8g2.print( "开机" );
  u8g2.setCursor( 0, 30 );
  u8g2.print( "WiFi to Link" );
  u8g2.sendBuffer();

  webServer.on("/pc", pc);//pc请求
  load();
  /* 获取网页信息服务开启 1/3 --开启网页服务*/
  webServer.on("/zdws", zdws);//高德天气keys
  webServer.on("/wsdw", wsdw);//城市id
  webServer.on("/yggd", yggd);//b站uid
  webServer.on("/txhm", txhm);//界面选择：1.B站粉丝界面；2天气界面； 3天气第二界面
  webServer.on("/zgwd", zgwd);//倒计时
  
  /* 初始化WiFi link tool */
  Serial.println( "设置 UDP" );
  Udp.begin( localPort );
  Serial.print( "Local port: " );
  Serial.println( Udp.localPort() );
  Serial.println( "正在等待同步" );

  if ( link() )
  {
    /*获取网页信息服务开启 2/3 --判断flash中是有数据*/
    EEPROM.begin(4096); 
    if(get_String(EEPROM.read(3000),3001).length()>50)
      {
      set_String(3000,3001,keys); //如果flash中的字符长度大于50，表明flash中没有数据，将keys的值写入flash
      }else{
      keys=get_String(EEPROM.read(3000),3001); //高德天气keys  如果flash中有参数，读取读取参数    
      }
    
    if(get_String(EEPROM.read(3100),3101).length()>50)
      {
      set_String(3100,3101,dq); 
      }else{
      dq=get_String(EEPROM.read(3100),3101);  //城市id 
      }
    
    if(get_String(EEPROM.read(3200),3201).length()>50)
      {
      set_String(3200,3201,UID);    
      }else{
      UID=get_String(EEPROM.read(3200),3201); //b站uid 
      }

    if(get_String(EEPROM.read(3300),3301).length() == 1 )
      {
        page=get_String(EEPROM.read(3300),3301);  //界面选择：1.B站粉丝界面；2天气界面； 3天气第二界面 
      }else{
        set_String(3300,3301,page);  
      } 

    EEPROM.get(3400,lastday);  // 倒计时参数，如果flash中没有参数，也没必要使用默认值
   
    Serial.println("01-高德天气keys：");
         Serial.println(keys);
    Serial.println("01-城市id：");
         Serial.println(dq);
    Serial.println("01-b站uid：");
         Serial.println(UID);     
    Serial.println("01-界面选择：");
         Serial.println(page);
    Serial.println("01-倒计时天数：");
         Serial.println(lastday);
    
    u8g2.setFont( u8g2_font_unifont_t_chinese2 );
    u8g2.setFontDirection( 0 );
    u8g2.clearBuffer();
    u8g2.setCursor( 0, 15 );
    u8g2.print( "开机" );
    u8g2.setCursor( 0, 30 );
    u8g2.print( "WiFi to Link" );
    u8g2.setCursor( 0, 45 );
    u8g2.print( "OK" );
    u8g2.setCursor( 0, 60 );
    u8g2.print( WiFi.localIP() );
    u8g2.sendBuffer();
    
      
    sjfx();
    delay( 1000 );
    donghua2();
    setSyncProvider( getNtpTime );
    previousday = day();    //初始化倒计时天数
    shuaxin();
    
  }else{
    u8g2.setFont( u8g2_font_unifont_t_chinese2 );
    u8g2.setFontDirection( 0 );
    u8g2.clearBuffer();
    u8g2.setCursor( 45, 15 );
    u8g2.print( "配网" );
    u8g2.setCursor( 0, 30 );
    u8g2.print( "Wifi Link To:" );
    u8g2.setCursor( 0, 45 );
    u8g2.print( "wifi_link_tool" );
    u8g2.setCursor( 0, 60 );
    u8g2.print( "IP:6.6.6.6" );
    u8g2.sendBuffer();
    delay( 5000 );
    u8g2.clearBuffer();
    u8g2.drawXBMP( 0, 0, 128, 64, wx );
    u8g2.sendBuffer(); 
  }
}
void loop()
{
  pant(); /* WiFi link tool 服务维持函数  请勿修改位置 */
  if ( link() )
  { 
    djs();          // 高考倒计时函数
  //  timerefrash();  //屏幕每分钟刷新
    
    unsigned long currentMillis = millis();    //旧的刷新屏幕的方法
    if ( currentMillis - previousMillis >= interval )
    {
       previousMillis = currentMillis;
       shuaxin(); 
    } 

    unsigned long currentMillis2 = millis();  //天气刷新
    if ( currentMillis2 - previousMillis2 >= interval2 )
    {
      previousMillis2 = currentMillis2;
      sjfx();
    }
    
    unsigned long currentMillis3 = millis();
    if ( currentMillis3 - previousMillis3 >= interval3 )//动画刷新
    {
      previousMillis3 = currentMillis3;
      donghua2();
      if(pcboot==1)
      { 
       pc(); 
      }else{
       shuaxin();
      }  
    }
  }
}
